part of '../widgets.dart';

typedef VanButtonType = VanType;

enum VanButtonSize { normal, large, small, mini }

enum VanButtonIconPosition { left, right }

enum VanButtonLoadingType { circular, spinner }

enum VanButtonNativeType { button, submit, reset }

class VanButton extends StatelessWidget {
  /// props - 类型，可选值为 primary success warning danger(默认: defaults)
  final VanButtonType type;

  /// props - 原生类型, 可选值为 submit reset (默认: button)
  final VanButtonNativeType nativeType;

  /// props - 尺寸，可选值为 large small mini(默认: normal)
  final VanButtonSize size;

  /// props - 按钮文字
  final String? text;

  /// props - 按钮颜色，支持传入 linear-gradient 渐变色
  final VanBgColor? color;

  /// props - 左侧图标名称或图片链接，等同于 Icon 组件的 name 属性
  final IconData? icon;

  /// props - 图标展示位置，可选值为 right(默认: left)
  final VanButtonIconPosition iconPosition;

  /// props - 是否为块级元素(默认: false)
  final bool block;

  /// props - 是否为朴素按钮(默认: false)
  final bool plain;

  /// props - 是否为方形按钮(默认: false)
  final bool square;

  /// props - 是否为圆形按钮(默认: false)
  final bool round;

  /// props - 是否禁用按钮(默认: false)
  final bool disabled;

  /// props - 是否使用 0.5px 边框(默认: false)
  final bool hairline;

  /// props - 是否显示为加载状态(默认: false)
  final bool loading;

  /// props - 加载状态提示文字
  final String? loadingText;

  /// props - 加载图标类型，可选值为 spinner(默认: circular)
  final VanButtonLoadingType loadingType;

  /// props - 加载图标大小，默认单位为 px(默认: 20px)
  final double loadingSize;

  /// props - 点击后跳转的目标路由对象，等同于 Vue Router 的 to 属性
  final String? to;

  /// props - 是否在跳转时替换当前页面历史(默认: false)
  final bool replace;

  final VanButtonStyle? style;

  /// events - 点击按钮，且按钮状态不为加载或禁用时触发
  final GestureTapCallback? onClick;

  /// slots - 按钮内容
  final dynamic child;

  /// slots - 自定义图标
  final Widget? childIcon;

  /// slots - 自定义加载图标
  final Widget? childLoading;

  const VanButton({
    super.key,
    this.type = VanButtonType.defaults,
    this.nativeType = VanButtonNativeType.button,
    this.size = VanButtonSize.normal,
    this.text,
    this.color,
    this.icon,
    this.iconPosition = VanButtonIconPosition.left,
    this.plain = false,
    this.block = false,
    this.disabled = false,
    this.hairline = false,
    this.loading = false,
    this.round = false,
    this.square = false,
    this.loadingText,
    this.loadingType = VanButtonLoadingType.circular,
    this.loadingSize = 20,
    this.to,
    this.replace = false,
    this.style,
    this.onClick,
    this.child,
    this.childIcon,
    this.childLoading,
  });

  VanButtonStyle getComputedStyle(BuildContext context) {
    if (style?.isNonNull == true) return style!;
    double? width;
    double? height = style?.height;
    EdgeInsets? padding = style?.padding;
    double? fontSize = style?.fontSize;
    double? lineHeight = style?.lineHeight;
    Color? color = style?.color;
    VanBgColor? background = this.color ?? style?.background;
    Color? borderColor = style?.borderColor;
    double? borderWidth = style?.borderWidth;
    BorderRadius? radius = style?.radius;
    double? opacity = style?.opacity;
    double? iconSize = style?.iconSize;
    double? loadingIconSize = style?.loadingIconSize;

    if (block) width ??= double.infinity;
    if (disabled) opacity ??= kVanButtonDisabledOpacity.toDouble(context);
    if (round) radius ??= kVanButtonRoundRadius.toBorderRadius(context);
    if (square) radius ??= BorderRadius.zero;

    if (type == VanButtonType.primary) {
      borderColor ??= kVanButtonPrimaryBorderColor.toColor(context);
      background ??= kVanButtonPrimaryBackground.toBgColor(context);
      color ??= kVanButtonPrimaryColor.toColor(context);
    } else if (type == VanButtonType.success) {
      borderColor ??= kVanButtonSuccessBorderColor.toColor(context);
      background ??= kVanButtonSuccessBackground.toBgColor(context);
      color ??= kVanButtonSuccessColor.toColor(context);
    } else if (type == VanButtonType.warning) {
      borderColor ??= kVanButtonWarningBorderColor.toColor(context);
      background ??= kVanButtonWarningBackground.toBgColor(context);
      color ??= kVanButtonWarningColor.toColor(context);
    } else if (type == VanButtonType.danger) {
      borderColor ??= kVanButtonDangerBorderColor.toColor(context);
      background ??= kVanButtonDangerBackground.toBgColor(context);
      color ??= kVanButtonDangerColor.toColor(context);
    }

    if (size == VanButtonSize.large) {
      width ??= double.infinity;
      height ??= kVanButtonLargeHeight.toDouble(context);
    } else if (size == VanButtonSize.small) {
      height ??= kVanButtonSmallHeight.toDouble(context);
      padding ??= kVanButtonSmallPadding.toEdgeInsets(context);
      fontSize ??= kVanButtonSmallFontSize.toDouble(context);
    } else if (size == VanButtonSize.mini) {
      height ??= kVanButtonMiniHeight.toDouble(context);
      padding ??= kVanButtonMiniPadding.toEdgeInsets(context);
      fontSize ??= kVanButtonMiniFontSize.toDouble(context);
    }

    if (this.color != null) {
      background = this.color;
      borderColor = this.color!.firstColor ?? borderColor;
      // 如果自定义了颜色，那字体默认主题系
      color = kVanButtonPrimaryColor.toColor(context);
    }

    if (plain) {
      borderColor = style?.borderColor ?? background?.color;
      color = style?.color ?? background?.firstColor ?? color;
      background = style?.background ?? kVanButtonPlainBackground.toBgColor(context) ?? VanBgColor(Colors.transparent);
    }

    height ??= kVanButtonDefaultHeight.toDouble(context);
    padding ??= kVanButtonNormalPadding.toEdgeInsets(context);
    fontSize ??= kVanButtonNormalFontSize.toDouble(context);
    lineHeight ??= kVanButtonDefaultLineHeight.toDouble(context);
    color ??= kVanButtonDefaultColor.toColor(context);
    background ??= kVanButtonDefaultBackground.toBgColor(context);
    borderColor ??= kVanButtonDefaultBorderColor.toColor(context) ?? Colors.transparent;
    borderWidth ??= kVanButtonBorderWidth.toDouble(context) ?? 0;
    radius ??= kVanButtonRadius.toBorderRadius(context);
    opacity ??= kVanButtonDisabledOpacity.toDouble(context) ?? 1;
    iconSize ??= kVanButtonIconSize.toDouble(context);
    loadingIconSize ??= kVanButtonLoadingIconSize.toDouble(context);

    iconSize ??= fontSize;
    loadingIconSize ??= iconSize;

    if (hairline) borderWidth = borderWidth / 2;

    return VanButtonStyle(
      width: width,
      height: height,
      padding: padding,
      fontSize: fontSize,
      lineHeight: lineHeight,
      color: color,
      background: background,
      borderColor: borderColor,
      borderWidth: borderWidth,
      radius: radius,
      opacity: opacity,
      iconSize: iconSize,
      loadingIconSize: loadingIconSize,
    );
  }

  @override
  Widget build(BuildContext context) {
    final style = getComputedStyle(context);

    VoidCallback? onTap;
    if (!disabled) {
      if (onClick != null) onTap = onClick;
      if (nativeType != VanButtonNativeType.button) {
        final form = VanForm.of(context);
        if (form != null) {
          onTap = () {
            if (nativeType == VanButtonNativeType.submit) {
              form.submit();
            } else if (nativeType == VanButtonNativeType.reset) {
              form.reset();
            }
          };
        }
      }
    }

    Border? border;
    if (style.borderWidth! > 0) {
      border = Border.all(color: style.borderColor!, width: style.borderWidth!);
    }
    Widget? widgetText;
    if (loading && loadingText?.isNotEmpty == true) {
      widgetText = Text(
        loadingText!,
        style: TextStyle(fontSize: style.fontSize, color: style.color, height: style.lineHeight),
      );
    } else if (child != null) {
      if (child is String) {
        widgetText = Text(child);
      } else if (child is Widget) {
        widgetText = child;
      } else {
        _logger.e("VanButton.child only type support [String] or [Widget].");
      }

      if (widgetText != null) {
        widgetText = DefaultTextStyle.merge(
          child: widgetText,
          style: TextStyle(fontSize: style.fontSize, color: style.color, height: style.lineHeight),
        );
      }
    } else if (text?.isNotEmpty == true) {
      widgetText = Text(
        text!,
        style: TextStyle(fontSize: style.fontSize, color: style.color, height: style.lineHeight),
      );
    }

    final List<Widget> children = [];

    if (loading) {
      Widget loadingWidget;
      if (childLoading != null) {
        final iconTheme = Theme.of(context).iconTheme.copyWith(size: style.loadingIconSize, color: style.color);
        loadingWidget = IconTheme(data: iconTheme, child: childLoading!);
      } else {
        loadingWidget = loadingType == VanButtonLoadingType.spinner
            //
            ? CupertinoActivityIndicator(color: style.color)
            : CircularProgressIndicator(color: style.color, strokeWidth: 1.2);

        loadingWidget = SizedBox(
          width: style.loadingIconSize,
          height: style.loadingIconSize,
          child: loadingWidget,
        );
      }

      loadingWidget = VanRotationWidget(
        duration: const Duration(seconds: 2),
        curve: Curves.linear,
        child: loadingWidget,
      );
      children.add(loadingWidget);
    } else if (childIcon != null) {
      final iconTheme = Theme.of(context).iconTheme.copyWith(size: style.iconSize, color: style.color);
      children.add(IconTheme(data: iconTheme, child: childIcon!));
    } else if (icon != null) {
      children.add(Icon(icon, color: style.color, size: style.iconSize! * style.fontSize!));
    }

    if (widgetText != null) {
      if (children.isNotEmpty) {
        children.add(SizedBox(width: kVanPaddingBase.toDouble(context)));
      }
      children.add(widgetText);
    }

    Widget? widget;
    if (children.length > 1 || !block) {
      widget = Row(
        mainAxisSize: block ? MainAxisSize.max : MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: iconPosition == VanButtonIconPosition.left ? children : children.reversed.toList(),
      );
    } else {
      widget = children.firstOrNull;
      if (widget != null) widget = Center(child: widget);
    }

    if (disabled) {
      return Opacity(
        opacity: style.opacity ?? 1,
        child: Container(
          width: style.width,
          height: style.height,
          padding: style.padding,
          decoration: BoxDecoration(
            color: style.background?.color,
            gradient: style.background?.gradient,
            borderRadius: style.radius,
            border: border,
          ),
          child: widget,
        ),
      );
    }

    widget = Container(
      decoration: BoxDecoration(
        color: style.background?.color,
        gradient: style.background?.gradient,
        borderRadius: style.radius,
        border: border,
      ),
      child: Material(
        color: Colors.transparent,
        child: InkWell(
          splashColor: style.background?.firstColor?.withOpacity(0.1),
          onTap: onTap,
          borderRadius: style.radius,
          child: Container(
            width: style.width,
            height: style.height,
            padding: style.padding,
            child: widget,
          ),
        ),
      ),
    );

    return widget;
  }
}
